package org.cainiao.api.lark.impl.imperative.docs.docs.apireference.document;

import lombok.RequiredArgsConstructor;
import org.cainiao.api.lark.dto.request.docs.apireference.ObtainAllBlocksOfDocumentRequest;
import org.cainiao.api.lark.dto.response.LarkDataResponse;
import org.cainiao.api.lark.dto.response.docs.docs.apireference.document.LarkBlockPage;
import org.cainiao.api.lark.imperative.docs.docs.apireference.document.Document;
import org.cainiao.api.lark.impl.util.converter.ResponseConverter;
import org.cainiao.api.lark.impl.util.provider.LarkAccessTokenProvider;
import org.cainiao.api.lark.util.Util;
import org.cainiao.common.util.QueryParameterUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpStatusCode;
import org.springframework.http.ResponseEntity;
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.reactive.function.client.WebClientResponseException;
import reactor.core.publisher.Mono;

import java.util.Map;

import static org.cainiao.api.lark.util.Util.DOCX_MODULE_URI;

/**
 * <br />
 * <p>
 * Author: Cai Niao(wdhlzd@163.com)<br />
 */
@RequiredArgsConstructor
public class WebClientDocument implements Document {

    private static final Logger LOGGER = LoggerFactory.getLogger(WebClientDocument.class);

    private final WebClient webClient;
    private final String baseUrl;
    /**
     * tenant_access_token 或 user_access_token
     */
    private final LarkAccessTokenProvider larkAccessTokenProvider;
    private final ResponseConverter responseConverter;

    @Override
    public ResponseEntity<LarkDataResponse<LarkBlockPage>> obtainAllBlocksOfDocument(
        String documentId, ObtainAllBlocksOfDocumentRequest obtainAllBlocksOfDocumentRequest) {

        String url = String.format("%s%s/documents/%s/blocks%s",
            baseUrl, DOCX_MODULE_URI, documentId, QueryParameterUtil.toQueryString(obtainAllBlocksOfDocumentRequest));
        return Util.getJsonWithAccessToken(webClient, url, larkAccessTokenProvider).exchangeToMono(clientResponse -> clientResponse
                .bodyToMono(new ParameterizedTypeReference<Map<String, Object>>() {
                })
                .map(responseMap -> {
                    HttpStatusCode statusCode = clientResponse.statusCode();
                    LOGGER.debug("obtainAllBlocksOfDocument() >>> httpStatusCode = {}", statusCode.value());
                    LOGGER.debug("obtainAllBlocksOfDocument() >>> responseMap = {}", responseMap);
                    return ResponseEntity
                        .status(statusCode)
                        .headers(clientResponse.headers().asHttpHeaders())
                        .body(responseConverter.convertToLarkBlockPageResponse(responseMap));
                }))
            .onErrorResume(WebClientResponseException.class, e -> Mono.just(ResponseEntity.status(e.getStatusCode()).build()))
            .block();
    }
}
